package util

import (
	"fmt"
	"log"
	"math/rand"
	"time"

	// "math/rand"

	"image"
	"image/draw"
	_ "image/png"
	"math"
	"os"

	"github.com/go-gl/gl/v3.3-core/gl"
	"github.com/go-gl/mathgl/mgl32"
)


func S(name *string) *uint8 {
	return gl.Str(*name + "\x00") 
}

func Herr(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func P(v... interface{}) {
	fmt.Println(v...)
}

func Radians(angle float32) float32 {
	return mgl32.DegToRad(angle)
}


func Sin(x float32) float32 {
	return float32(math.Sin(float64(x)))
}

func Cos(x float32) float32 {
	return float32(math.Cos(float64(x)))
}

// 加载图片
func LoadImage(fname string) ([]uint8, image.Rectangle, error) {
	f, err := os.Open(fname)
	if err != nil {
		return nil, image.Rectangle{}, err
	}
	defer f.Close()
	img, _, err := image.Decode(f)
	if err != nil {
		return nil, image.Rectangle{}, err
	}
	// rgba图片格式
	rgba := image.NewRGBA(img.Bounds())
	// 将img画入rgba中去
	draw.Draw(rgba, rgba.Bounds(), img, img.Bounds().Min, draw.Src)
	return rgba.Pix, img.Bounds(), nil
}
// var p = perlin.NewPerlin(2,2,3,10000)

// // Perlin --> 柏林噪声
// func PerlinNoise(x,y int) int {
// 	scale := 10.0
// 	xx := float64(x)/scale
// 	yy := float64(y)/scale
// 	k := int(p.Noise2D(xx,yy)*scale*10)
// 	// k := int(math.Abs((p.Noise2D(xx,yy)))*30)
// 	// if k>=15 {
// 	// 	return 15
// 	// }
// 	// if k<=10 {
// 	// 	return 10
// 	// }
// 	return k
// }




func noise(x, y int64, seed int64) float64 {
	n := x + y*57 + seed*7
	fn := (n << 13) ^ n
	return (1.0 - float64((fn*(fn*fn*15731+789221)+1376312589)&0x7fffffff)/float64(0x40000000))
}

func smoothedNoise(x float64, y float64, seed int64) float64 {
	xint := int64(math.Trunc(x))
	yint := int64(math.Trunc(y))

	corners := (noise(xint-1, yint-1, seed) + noise(xint+1, yint-1, seed) + noise(xint-1, yint+1, seed) + noise(xint+1, yint+1, seed)) / 16
	sides := (noise(xint-1, yint, seed) + noise(xint+1, yint, seed) + noise(xint, yint-1, seed) + noise(xint, yint+1, seed)) / 8
	center := noise(xint, yint, seed) / 4
	return corners + sides + center
}

func interpolate(a, b, x float64) float64 {
	ft := x * math.Pi
	f := (1 - math.Cos(ft)) * 0.5
	return a*(1-f) + b*f
}

func interpolatedNoise(x, y float64, seed int64) float64 {

	xint := math.Trunc(x)
	xfrac := x - xint

	yint := math.Trunc(y)
	yfrac := y - yint

	v1 := smoothedNoise(xint, yint, seed)
	v2 := smoothedNoise(xint+1, yint, seed)
	v3 := smoothedNoise(xint, yint+1, seed)
	v4 := smoothedNoise(xint+1, yint+1, seed)

	i1 := interpolate(v1, v2, xfrac)
	i2 := interpolate(v3, v4, xfrac)

	return interpolate(i1, i2, yfrac)

}

func Noise2D(x, y float64) (value float64) {

	var seed int64 = 100
	alpha := 2.0
	beta := 2.0
	octaves := 4
	scale := 1.0
	for i := 0; i < octaves; i++ {
		value += interpolatedNoise(x, y, seed) / scale

		scale *= alpha
		x *= beta
		y *= beta
	}

	return
}


func init() {
	rand.Seed(time.Now().Unix())
}

func PerlinNoise(mp [][]int) {
	ox := float64(rand.Int31n(10000))/10000.0
	oy := float64(rand.Int31n(10000))/10000.0
	scale := 1.0
	for i:=0;i<15;i++ {
		for j:=0;j<15;j++ {
			xs := (ox + float64(i)/15.0) * scale
			ys := (oy + float64(j)/15.0) * scale
			hei := Noise2D(xs,ys)
			k := -1*hei*35
			if k<5 {
				k = 5
			}
			if k>=15 {
				k = 14
			}
			mp[i][j] = int(k)
		}
	}
}


type IV3 [3]int


func (i IV3) Top() IV3 {
	return IV3{
		i[0],
		i[1]+1,
		i[2],
	}
} 


func (i IV3) Down() IV3 {
	return IV3{
		i[0],
		i[1]-1,
		i[2],
	}
} 


func (i IV3) Left() IV3 {
	return IV3{
		i[0]-1,
		i[1],
		i[2],
	}
} 

func (i IV3) Right() IV3 {
	return IV3{
		i[0]+1,
		i[1],
		i[2],
	}
} 

func (i IV3) Front() IV3 {
	return IV3{
		i[0],
		i[1],
		i[2]-1,
	}
}

func (i IV3) Back() IV3 {
	return IV3{
		i[0],
		i[1],
		i[2]+1,
	}
}


func (i IV3) Block() int {
	x := int(math.Floor(float64(i[0])/15))
	y := int(math.Floor(float64(i[2])/15))
	return x*100000 + y
}

